

#pragma once
#include <memory>
#include <unordered_map>

#include "Utility/Algebra/AlgebraicTypes.h"

#include "DataStructure/Common/Id.h"
#include "DataStructure/Input/Table/TABLEDObject.h"
#include "DataStructure/Input/Load/RLOAD1Data.h"
#include "DataStructure/Input/Load/RLOAD2Data.h"
#include "DataStructure/Input/Load/TLOAD1Data.h"
#include "DataStructure/Input/Load/TLOAD2Data.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Load/ILSEQService.h"
#include "DBManager/IService/Input/Load/ILoadCombinationService.h"

#include "TaskExport.h"

/**
 * @brief  查询载荷集id 需要的静力载荷数据
 * 
 * @tparam LoadType 支持类型可以为 TLOAD1Data，TLOAD2Data, RLOAD1Data, RLOAD1Data
 * @param    load       载荷数据
 * @param    db         数据库
 * @param    LoadsetId  工况数据中的loadSet编号，用于查找对应的 lseq
 * @return   
 * @author   wanghuan
 * @date     2025.7.11
 */
template <typename LoadType>
SG::DataStructure::Common::IdArray
getStaticLoadId (LoadType load, SG::DBManager::DBServiceFactorySP db, SG::DataStructure::Common::Id LoadsetId)
{
    SG::DataStructure::Common::Id      loadId;
    if (0 != LoadsetId)
    {
      // excited -sid pair is unique
      SG::DataStructure::FEM::LSEQData lseq;
      db->get<SG::DBManager::ILSEQService> ()->FindByLoadId (LoadsetId, load.m_DAREA, lseq);
      loadId = lseq.m_LID;
    }
    else
    {
      // no loadset，使用静力载荷
      loadId = static_cast<SG::DataStructure::Common::Id> (load.m_DAREA);
    }
    
    SG::DataStructure::Common::IdArray loadIds;
    SG::DataStructure::FEM::LoadCombination loadGroup;
    const auto                              isLoadCase = db->get<SG::DBManager::ILoadCombinationService> ()->FindById (loadId, loadGroup);

    if (SG::DataStructure::Common::Status::STATUS_Success == isLoadCase)
    {
        for (const auto& item : loadGroup.m_Items)
        {
            loadIds.push_back (item.m_subSet);
        }
    }
    else
    {
        loadIds.push_back (loadId);
    }

    return loadIds;
}

/**
 * @brief    动力学时域载荷计算基类
 * 
 * 频域载荷需要复数形式载荷向量，因此此处重构基类名称
 * 
 * @author   wanghuan
 * @date     2025.10.11 modify
 */
class Task_DECLSPEC TimeDynamicLoad
{
  public:
    virtual ~TimeDynamicLoad () = default;

    /**
     * @brief    计算载荷的空间分布
     *
     * @param    db
     * @param    subcaseId
     * @return
     * @author   wangjunwen
     * @date     2025.07.05
     */
    virtual SG::DataStructure::Common::Status computeA (SG::DBManager::DBServiceFactorySP   db,
                                                        const SG::DataStructure::Common::Id subcaseId) = 0;

    /// @brief 插值某时刻或者频率点的载荷向量
    virtual SG::Algebra::Vec_t Interplate (SG::DBManager::DBServiceFactorySP db, const SG::Algebra::Real_t t) const = 0;
};

using TimeDynamicLoadP = std::shared_ptr<TimeDynamicLoad>;

class Task_DECLSPEC TLoad1Calc : public TimeDynamicLoad
{
  public:
    TLoad1Calc (const SG::DataStructure::FEM::TLOAD1Data& tload1,
                SG::DataStructure::Common::Id             loadSetId,
                SG::DataStructure::Common::Real           S);

    SG::DataStructure::Common::Status computeA (SG::DBManager::DBServiceFactorySP db, const SG::DataStructure::Common::Id subcaseId);

    SG::Algebra::Vec_t Interplate (SG::DBManager::DBServiceFactorySP db, const SG::Algebra::Real_t t) const override;

    // 函数仅仅供编写单元测试时使用
    const SG::Algebra::Vec_t& getStaticForce () const
    {
        return m_staticF;
    }

  private:
    SG::DataStructure::FEM::TLOAD1Data  m_load;
    SG::DataStructure::FEM::TABLEDObjectP m_timeTab;

    SG::DataStructure::Common::Id                m_loadsetId;
    SG::DataStructure::Common::Real              m_S;
    SG::Algebra::Vec_t                           m_staticF;
    std::unordered_map<int, SG::Algebra::Real_t> m_delayMap;
};

class TLoad2Calc : public TimeDynamicLoad
{
  public:
    TLoad2Calc (const SG::DataStructure::FEM::TLOAD2Data& tload2,
                SG::DataStructure::Common::Id             loadSetId,
                SG::DataStructure::Common::Real           S);

    SG::DataStructure::Common::Status computeA (SG::DBManager::DBServiceFactorySP   db,
                                                const SG::DataStructure::Common::Id subcaseId) override;

    SG::Algebra::Vec_t Interplate (SG::DBManager::DBServiceFactorySP db, const SG::Algebra::Real_t t) const override;

  private:
    SG::DataStructure::FEM::TLOAD2Data m_load;
    SG::DataStructure::Common::Id      m_loadsetId;
    SG::DataStructure::Common::Real    m_S;

    SG::Algebra::Vec_t                           m_staticF;
    std::unordered_map<int, SG::Algebra::Real_t> m_delayMap;
};

class Task_DECLSPEC FreqDynamicLoad
{
  public:
    virtual ~FreqDynamicLoad () = default;

    /**
     * @brief    计算载荷的空间分布
     *
     * @param    db
     * @param    subcaseId
     * @return
     * @author   wanghuan
     * @date     2025.10.11
     */
    virtual SG::DataStructure::Common::Status computeA (SG::DBManager::DBServiceFactorySP   db,
                                                        const SG::DataStructure::Common::Id subcaseId) = 0;

    /// @brief 插值某时刻或者频率点的载荷向量
    virtual SG::Algebra::ComplexVec_t Interplate (SG::DBManager::DBServiceFactorySP db, const SG::Algebra::Real_t t) const = 0;
};
using FreqDynamicLoadP = std::shared_ptr<FreqDynamicLoad>;

class RLoad1Calc : public FreqDynamicLoad
{
  public:
    RLoad1Calc (const SG::DataStructure::FEM::RLOAD1Data& rload1,
                SG::DataStructure::Common::Id             loadsetId,
                SG::DataStructure::Common::Real           S);

    SG::DataStructure::Common::Status computeA (SG::DBManager::DBServiceFactorySP   db,
                                                const SG::DataStructure::Common::Id subcaseId) override;

    SG::Algebra::ComplexVec_t Interplate (SG::DBManager::DBServiceFactorySP db, const SG::Algebra::Real_t t) const override;

  private:
    SG::DataStructure::FEM::RLOAD1Data  m_rload1;
    SG::DataStructure::FEM::TABLEDObjectP m_TC;
    SG::DataStructure::FEM::TABLEDObjectP m_TD;
    SG::Algebra::Vec_t                  m_staticF;
    SG::DataStructure::Common::Real     m_S;
    SG::DataStructure::Common::Id       m_loadsetId;
};

class Task_DECLSPEC RLoad2Calc : public FreqDynamicLoad
{
  public:
    RLoad2Calc (const SG::DataStructure::FEM::RLOAD2Data& rload2,
                SG::DataStructure::Common::Id             loadsetId,
                SG::DataStructure::Common::Real           S);

    SG::DataStructure::Common::Status computeA (SG::DBManager::DBServiceFactorySP   db,
                                                const SG::DataStructure::Common::Id subcaseId) override;

    SG::Algebra::ComplexVec_t Interplate (SG::DBManager::DBServiceFactorySP db, const SG::Algebra::Real_t t) const override;

    // 函数仅仅供编写单元测试时使用
    const SG::Algebra::Vec_t& getStaticForce () const
    {
        return m_staticF;
    }

  private:
    SG::DataStructure::FEM::RLOAD2Data  m_rload2;
    SG::DataStructure::FEM::TABLEDObjectP m_timeTabB;
    SG::Algebra::Vec_t                  m_staticF;
    SG::DataStructure::Common::Real     m_S;
    SG::DataStructure::Common::Id       m_loadsetId;
    std::unordered_map<int, SG::Algebra::Real_t>  m_delayMap;
};